package org.jeecg.common.job;

import org.jeecg.common.COSMOS;
import org.jeecg.common.job.data.vo.JobInfoVo;
import org.jeecg.common.job.enums.JobConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class JobManageCenter {

    private static Logger LG = LoggerFactory.getLogger(JobManageCenter.class);
    private static Map<String, SchedulerActive> list = new ConcurrentHashMap<String, SchedulerActive>();

    /**
     * 添加任务
     *
     * @param id         任务ID
     * @param cycleTime  时间计划
     * @param beanName   Spring Bean名称
     * @param beanMethod 方法名称
     * @param mode       执行模式，1.所有节点执行  0.互斥节点， 默认为0
     * @param nodeName   节点名称
     * @return
     */
    public static JobConstants.JobManagerStatus addJob(String id, String cycleTime, String beanName, String beanMethod, Integer mode, String nodeName, Date updateTime) {
        if(!JobConstants.ENABLE) {
            return JobConstants.JobManagerStatus.NOT_OPEN;
        }
        String key = beanName + beanMethod;
        if (list.containsKey(key)) {
            LG.warn("定时任务已存在[" + key + "]，忽略。");
            return JobConstants.JobManagerStatus.FAIL;
        }
        SchedulerActive schedulerActive = new SchedulerActive(id, cycleTime, beanName, beanMethod, mode, nodeName, updateTime);
        JobConstants.JobManagerStatus status = schedulerActive.start();
        if (status == JobConstants.JobManagerStatus.SUCCESS) {
            list.put(key, schedulerActive);
        }
        return status;
    }

    /**
     * 添加任务
     *
     * @param id         任务ID
     * @param beanName   Spring Bean名称
     * @param beanMethod 方法名称
     * @return
     */
    public static JobConstants.JobManagerStatus deleteJob(String id, String beanName, String beanMethod) {
        if(!JobConstants.ENABLE) {
            return JobConstants.JobManagerStatus.NOT_OPEN;
        }
        String key = beanName + beanMethod;
        if (!list.containsKey(key)) {
            LG.warn("定时任务不存在[" + key + "]，忽略。");
            return JobConstants.JobManagerStatus.FAIL;
        }
        SchedulerActive schedulerActive = list.get(key);
        JobConstants.JobManagerStatus status = schedulerActive.stop();
        if (status == JobConstants.JobManagerStatus.SUCCESS) {
            list.remove(key);
        }
        return status;
    }

    /**
     * 添加任务
     *
     * @param id         任务ID
     * @return
     */
    public static JobConstants.JobManagerStatus execJob(String id) {
        if(!JobConstants.ENABLE) {
            return JobConstants.JobManagerStatus.NOT_OPEN;
        }
        Iterator<String> keys = list.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next();
            SchedulerActive schedulerActive = list.get(key);
            if(schedulerActive.getJobId().equals(id)){
                Object execBean = COSMOS.getBean(schedulerActive.getBeanName());
                Method method = ReflectionUtils.findMethod(execBean.getClass(), schedulerActive.getBeanMethod());
                // 反射执行方法
                ReflectionUtils.invokeMethod(method, execBean);
                break;
            }
        }
        return JobConstants.JobManagerStatus.SUCCESS;
    }

    /**
     * 删除定时任务
     * @param jobList
     */
    public static void refreshJob(List<JobInfoVo> jobList){
        if(!JobConstants.ENABLE) {
            return;
        }

        // 判断是否删除
        Iterator<String> keys = list.keySet().iterator();
        while(keys.hasNext()){
            String key = keys.next();
            SchedulerActive schedulerActive = list.get(key);
            if(schedulerActive.getJobId().startsWith("-")){
                continue;
            }
            boolean bl = jobList.stream().anyMatch(m-> m.getId().equals(schedulerActive.getJobId()) && m.getUpdateTime().getTime() == schedulerActive.getUpdateTime().getTime());
            if(!bl){
                deleteJob(schedulerActive.getJobId(), schedulerActive.getBeanName(), schedulerActive.getBeanMethod());
            }
        }

        // 判断是否新增
        jobList.forEach(n->{
            boolean bl = list.values().stream().anyMatch(m-> m.getJobId().equals(n.getId()));
            if(!bl){
                addJob(n.getId(), n.getCycleTime(), n.getBeanName(), n.getBeanMethod(), n.getExecuteMode(), n.getNodeName(), n.getUpdateTime());
            }
        });
    }
}
